package com.wzw.programming_conference.service.Imp;
import com.google.common.base.CharMatcher;
import com.wzw.programming_conference.exception.ConferenceException;
import com.wzw.programming_conference.pojo.*;
import com.wzw.programming_conference.service.ConferenceService;
import com.wzw.programming_conference.service.Session;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author wzw
 * @date 2023/3/21
 */
@Service
public class ConferenceServiceImp implements ConferenceService {

    private static final Map<String,Track> tracks=new ConcurrentHashMap<>();


    @Override
    public List<Talk> listStringToTalk(List<String> list) {

        //1.0版 原始语法
//        ArrayList<Talk> arrayList = new ArrayList();
//        for (String s : list) {
//            int time = Integer.parseInt(CharMatcher.javaDigit().retainFrom(s));
//            String title = s.replaceAll("\\d+[a-z]+", "");
//            Talk talk = new Talk(title, time);
//            arrayList.add(talk);
//        }
//        return arrayList;

//        2.0版      //没有处理时间单位lightning
//      return   list.stream().map(s->new Talk(s.replaceAll("\\d+[a-z]+", ""),
//              Integer.parseInt(CharMatcher.javaDigit().retainFrom(s))))
//              .collect(Collectors.toList());

        //3.0版   //可能会匹配到标题中的数字
//        return   list.stream().map(str->str.endsWith("lightning")?str.replace("lightning","5min"):str)
//                .map(s->new Talk(s.replaceAll("\\d+[a-z]+", ""),
//                        Integer.parseInt(CharMatcher.javaDigit().retainFrom(s))))
//                .collect(Collectors.toList());
//

        //4.0版  没有禁止标题中存在数字 使用String方法代替正则
//       return list.stream()
//                .map(str->str.endsWith("lightning")?str.replace("lightning","5min"):str)
//                .map(str->new Talk(str.substring(0,str.lastIndexOf(" ")),
//                        Integer.parseInt(str.substring(str.lastIndexOf(" ")).replace("min","").trim())))
//               .collect(Collectors.toList());


        //5.0  解决标题中存在数字的问题，以及talk时间边界的问题
//        return list.stream()
//                .map(str->str.endsWith("lightning")?str.replace("lightning","5min"):str)
//                .filter(str->!titleHaveDigit(str.substring(0,str.lastIndexOf(" "))))
//                .filter(str->judgeTalkTimeDuration(str.substring(str.lastIndexOf(" ")).replace("min","").trim()))
//                .map(str->new Talk(str.substring(0,str.lastIndexOf(" ")),
//                        Integer.parseInt(str.substring(str.lastIndexOf(" ")).replace("min","").trim())))
//                .collect(Collectors.toList());
//    }

    //5.0  解决标题中存在数字的问题，以及talk时间边界的问题
        return list.stream()
                .map(str->str.endsWith("lightning")?str.replace("lightning","5min"):str)
            .filter(str->!titleHaveDigit(str.substring(0,str.lastIndexOf(" "))))
            .filter(str-> judgeTalkTimeFormat(str.substring(str.lastIndexOf(" ")+1)))
            .filter(str->judgeTalkTimeDuration(str.substring(str.lastIndexOf(" ")+1).replace("min","").trim()))
            .map(str->new Talk(str.substring(0,str.lastIndexOf(" ")),
            Integer.parseInt(str.substring(str.lastIndexOf(" ")).replace("min","").trim())))
            .collect(Collectors.toList());
}
    public static boolean titleHaveDigit(String title) {
      boolean haveDigit=  !StringUtils.isBlank(CharMatcher.javaDigit().retainFrom(title));
      if (haveDigit){
         throw new ConferenceException("标题不能有数字");
      }
      return false;
    }

    public static String handlerLighting(String str){//todo
        String[] arr = str.trim().split("\\d*");
        Arrays.stream(arr).forEach(System.out::println);
        if (arr.length==2){
         return String.valueOf(Integer.parseInt(arr[0])*5);
        }
        return "5min";
    }

    public static boolean judgeTalkTimeFormat(String talkTime){
        if (!talkTime.matches("^[1-9]+\\d*min$")){
            throw new ConferenceException("时间格式不符合要求");
        }
        return true;
    }
    public static boolean judgeTalkTimeDuration(String timeStr){
        int time = Integer.parseInt(timeStr);
        if (time>240){
            throw new ConferenceException("会议时间过长");
        }
        return true;
    }


    public List<Talk> sortTalkByDuration(List<Talk> allTalks){
        allTalks.sort(Collections.reverseOrder());
        return allTalks;
    }

    //1.0版
//   public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        Session morningSession = Session.getMorningSession();
//        Session afternoonSession = Session.getAfternoonSession();
//        Track track = Track.getTrack(trackNumber);
//        track.addSession(morningSession);
//        track.addSession(afternoonSession);
//        for (Talk talk : talks) {
//           if (morningSession.canAddTalk(talk)){
//               morningSession.addTalk(talk);
//           }else if (afternoonSession.canAddTalk(talk)){
//                   afternoonSession.addTalk(talk);
//           }else if(!track.getAfterNoonSession().canAddTalk(talk)){
//                   track=Track.getTrack(++trackNumber);
//                   morningSession = Session.getMorningSession();
//                   afternoonSession=Session.getAfternoonSession();
//                   track.addSession(morningSession);
//                   track.addSession(afternoonSession);
//               }
//           }
//        }
//        return Track.getTracks();
//    }


//    //2.0版  将 tracks(Map)从Track对象中移动到当前类，Track类只应该存放其属性和行为
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        String trackNumberStr = String.valueOf(trackNumber);
//        Track track= tracks.containsKey(trackNumberStr)?
//               tracks.get(trackNumberStr):getTrackAndPutToTracks(trackNumber);
//        Session morningSession = Session.getMorningSession();
//        Session afternoonSession = Session.getAfternoonSession();
//        track.addSession(morningSession);
//        track.addSession(afternoonSession);
//        for (Talk talk : talks) {
//            if (morningSession.canAddTalk(talk)) {
//                morningSession.addTalk(talk);
//            } else if (afternoonSession.canAddTalk(talk)) {
//                afternoonSession.addTalk(talk);
//            } else {
//                if (!track.getAfterNoonSession().canAddTalk(talk)) {
//                    trackNumber++;
//                    track = tracks.containsKey(String.valueOf(trackNumber))?
//                            tracks.get(String.valueOf(trackNumber)):getTrackAndPutToTracks(trackNumber);
//                    morningSession = Session.getMorningSession();
//                    afternoonSession = Session.getAfternoonSession();
//                    track.addSession(morningSession);
//                    track.addSession(afternoonSession);
//                }
//            }
//        }
//        return getTracks();
//        }

//    //3.0版  减少if...else的使用
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        String trackNumberStr = String.valueOf(trackNumber);
//        Track track= tracks.containsKey(trackNumberStr)?
//                tracks.get(trackNumberStr):getTrackAndPutToTracks(trackNumber);
//        Session morningSession = Session.getMorningSession();
//        Session afternoonSession = Session.getAfternoonSession();
//        track.addSession(morningSession);
//        track.addSession(afternoonSession);
//        for (Talk talk : talks) {
//            boolean addTalk= morningSession.canAddTalk(talk)?morningSession.addTalk(talk): judgeAndAddTalk(afternoonSession,talk);
//            if (!addTalk){
//                trackNumber++;
//                    track = tracks.containsKey(String.valueOf(trackNumber))?
//                            tracks.get(String.valueOf(trackNumber)):getTrackAndPutToTracks(trackNumber);
//                    morningSession = Session.getMorningSession();
//                    afternoonSession = Session.getAfternoonSession();
//                    track.addSession(morningSession);
//                    track.addSession(afternoonSession);
//            }
//        }
//        return getTracks();
//    }

////4.0版  将统一实现提到抽象类
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        String trackNumberStr = String.valueOf(trackNumber);
//        Track track= tracks.containsKey(trackNumberStr)?
//                tracks.get(trackNumberStr):getTrackAndPutToTracks(trackNumber);
//        Session morningSession = new MorningSession(TimePoint.MORNING_START_TIME, TimePoint.MORNING_START_TIME, TimePoint.LUNCH_START_TIME);
//        Session afternoonSession = new AfternoonSession(TimePoint.AFTERNOON_START_TIME, TimePoint.AFTERNOON_START_TIME, TimePoint.NETWORKING_START_TIME);
//        track.addSession(morningSession);
//        track.addSession(afternoonSession);
//        for (Talk talk : talks) {
//            boolean addTalk= morningSession.canAddTalk(talk)?morningSession.addTalk(talk): judgeAndAddTalk(afternoonSession,talk);
//            if (!addTalk){
//                trackNumber++;
//                    track = tracks.containsKey(String.valueOf(trackNumber))?
//                            tracks.get(String.valueOf(trackNumber)):getTrackAndPutToTracks(trackNumber);
//                    morningSession = new MorningSession(TimePoint.MORNING_START_TIME, TimePoint.MORNING_START_TIME, TimePoint.LUNCH_START_TIME);
//                    afternoonSession = new AfternoonSession(TimePoint.AFTERNOON_START_TIME, TimePoint.AFTERNOON_START_TIME, TimePoint.NETWORKING_START_TIME);
//                    track.addSession(morningSession);
//                    track.addSession(afternoonSession);
//            }
//        }
//        return getTracks();
//    }


////    //5.0  存在的问题，一个方法做了多件事，不够清晰明了track重新赋值导致可读性变差
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        Track track= getTrackFromMapOrNew(trackNumber);
//        addSessionToTrack(track);
//        Session  morningSession=track.getMorningSession();
//        Session afternoonSession=track.getAfterNoonSession();
//        for (Talk talk : talks) {
//            boolean addTalk= morningSession.canAddTalk(talk)?morningSession.addTalk(talk): judgeAndAddTalk(afternoonSession,talk);
//            if (!addTalk){
//                trackNumber++;
//                track = getTrackFromMapOrNew(trackNumber);
//                addSessionToTrack(track);
//                morningSession = track.getMorningSession();
//                afternoonSession = track.getAfterNoonSession();
//            }
//        }
//        return getTracks();
//    }



    //6.0
//    addTalk= morningSession.canAddTalk(talk)?
//                    morningSession.addTalk(talk):
//                    addTalkToSession(afternoonSession,talk);  代码逻辑类似 重复，考虑优化
//    必须添加network event 优先级高于普通talk
//    如果上午可以放完就无需创建下午的session
//    使用log4j输出日志
    //以下代码逻辑重复，应优化放到循环中
    //Track track = new Track(trackNumber);
    //        tracks.put(String.valueOf(trackNumber),track);
    //        addSessionToTrack(track);
    //        Session  morningSession=track.getMorningSession();
    //        Session afternoonSession=track.getAfterNoonSession();

//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        Track track = new Track(trackNumber);
//        tracks.put(String.valueOf(trackNumber),track);
//        addSessionToTrack(track);
//        Session  morningSession=track.getMorningSession();
//        Session afternoonSession=track.getAfterNoonSession();
//        for (Talk talk : talks) {
//            boolean addTalk= morningSession.canAddTalk(talk)?
//                    morningSession.addTalk(talk):
//                    addTalkToSession(afternoonSession,talk);
//            if (!addTalk){
//                trackNumber++;
//                Track newTrack = new Track(trackNumber);
//                tracks.put(String.valueOf(trackNumber),newTrack);
//                addSessionToTrack(newTrack);
//                morningSession = newTrack.getMorningSession();
//                afternoonSession = newTrack.getAfterNoonSession();
//                morningSession.addTalk(talk);
//            }
//        }
//        return getTracks();
//    }

//        //7.0 解决三元运算的可读性
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        Track track = new Track(trackNumber);
//        tracks.put(String.valueOf(trackNumber),track);
//        addSessionToTrack(track);
//        Session  morningSession=track.getMorningSession();
//        Session afternoonSession=track.getAfterNoonSession();
//        for (Talk talk : talks) {
//            boolean addTalk= addTalkToSession(morningSession,talk);
//            if (!addTalk){
//                addTalk= addTalkToSession(afternoonSession,talk);
//            }
//            if (!addTalk){
//                trackNumber++;
//                Track newTrack = new Track(trackNumber);
//                tracks.put(String.valueOf(trackNumber),newTrack);
//                addSessionToTrack(newTrack);
//                morningSession = newTrack.getMorningSession();
//                afternoonSession = newTrack.getAfterNoonSession();
//                morningSession.addTalk(talk);
//            }
//        }
//        return getTracks();
//    }


//    8.0 解决多创建一个afternoonSession对象的问题
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        int trackNumber=1;
//        Track track = new Track(trackNumber);
//        tracks.put(String.valueOf(trackNumber),track);
//        addSessionToTrack(track);
//        Session  morningSession=track.getMorningSession();
//        Session afternoonSession=null;
//        for (Talk talk : talks) {
//            boolean addTalk= addTalkToSession(morningSession,talk);
//            if (!addTalk){
//                if(null==afternoonSession){
//                  afternoonSession= AfternoonSession.getAfternoonSession();
//                  track.addSession(afternoonSession);
//                }
//                addTalk= addTalkToSession(afternoonSession,talk);
//            }
//            if (!addTalk){
//                trackNumber++;
//               track = new Track(trackNumber);
//                tracks.put(String.valueOf(trackNumber),track);
//                addSessionToTrack(track);
//                morningSession = track.getMorningSession();
//                morningSession.addTalk(talk);
//                afternoonSession=null;
//            }
//        }
//        return getTracks();
//    }

//9.0简化多个if操作
    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
        int trackNumber=1;
        Track track = new Track(trackNumber);
        tracks.put(String.valueOf(trackNumber),track);
        addSessionToTrack(track);
        Session  morningSession=track.getMorningSession();
        Session afternoonSession=null;
        for (Talk talk : talks) {
            if (!addTalkToSession(morningSession,talk)) {
                afternoonSession= null== afternoonSession ?
                        track.addSession(AfternoonSession.getAfternoonSession())
                        :afternoonSession;
                if (!addTalkToSession(afternoonSession,talk)) {
                    ++trackNumber;
                    track = new Track(trackNumber);
                    tracks.put(String.valueOf(trackNumber),track);
                    addSessionToTrack(track);
                    morningSession = track.getMorningSession();
                    addTalkToSession(morningSession, talk);
                    afternoonSession = null;
                }
            }
        }
        return getTracks();
    }




    //因为lambda替换for循环，但lambda内不能修对变量重新赋值，使用了数组，可读性？
//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        final int[] trackNumber = {1};
//        Track track = new Track(trackNumber[0]);
//        tracks.put(String.valueOf(trackNumber[0]),track);
//        addSessionToTrack(track);
//        final Session[] morningSession = {track.getMorningSession()};
//        final Session[] afternoonSession = {track.getAfterNoonSession()};
//
//        talks.forEach(talk -> {
//            boolean addTalk= addTalkToSession(morningSession[0],talk);
//            if (!addTalk){
//                addTalk= addTalkToSession(afternoonSession[0],talk);
//            }
//            if (!addTalk){
//                trackNumber[0]++;
//                Track newTrack = new Track(trackNumber[0]);
//                tracks.put(String.valueOf(trackNumber[0]),newTrack);
//                addSessionToTrack(newTrack);
//                morningSession[0] = newTrack.getMorningSession();
//                afternoonSession[0] = newTrack.getAfterNoonSession();
//                morningSession[0].addTalk(talk);
//            }
//        });
//        return getTracks();
//    }


//    public Map<String,Track> fillTalkToTrack(List<Talk> talks){
//        final int[] trackNumber = {1};
//        final Track[] track = {new Track(trackNumber[0])};
//        tracks.put(String.valueOf(trackNumber[0]), track[0]);
//        addSessionToTrack(track[0]);
//        final Session[] morningSession = {track[0].getMorningSession()};
//        final Session[] afternoonSession =new Session[1];
//
//        talks.forEach(talk -> {
//            boolean addTalk= addTalkToSession(morningSession[0],talk);
//            if (!addTalk) {
//                if (null == afternoonSession[0]) {
//                    afternoonSession[0]= AfternoonSession.getAfternoonSession();
//                    track[0].addSession(afternoonSession[0]);
//                }
//                addTalk= addTalkToSession(afternoonSession[0],talk);
//                }
//            if (!addTalk){
//                trackNumber[0]++;
//                track[0] = new Track(trackNumber[0]);
//                tracks.put(String.valueOf(trackNumber[0]), track[0]);
//                addSessionToTrack(track[0]);
//                morningSession[0] = track[0].getMorningSession();
//                morningSession[0].addTalk(talk);
//                afternoonSession[0]=null;
//            }
//        });
//        return getTracks();
//    }










    public static void addSessionToTrack(Track track){
       MorningSession morningSession = new MorningSession(TimePoint.MORNING_START_TIME, TimePoint.MORNING_START_TIME, TimePoint.LUNCH_START_TIME);
//        AfternoonSession afternoonSession = new AfternoonSession(TimePoint.AFTERNOON_START_TIME, TimePoint.AFTERNOON_START_TIME, TimePoint.NETWORKING_START_TIME,TimePoint.NETWORKING_START_TIME);
        track.addSession(morningSession);
//        track.addSession(afternoonSession);
    }

    @Override
    public List readMeetingFile(String fileName){
        if (StringUtils.isBlank(fileName)){
            throw new RuntimeException("文件名不能为空");
        }
        try {
        String filePath= Objects.requireNonNull(this.getClass().getClassLoader().getResource(fileName)).getPath();
             return FileUtils.readLines(new File(filePath), StandardCharsets.UTF_8.toString());
        } catch (NullPointerException e) {
          throw  new RuntimeException("文件不存在");
        }catch (IOException e){
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

    public static boolean addTalkToSession(Session session, Talk talk){
        if (session.canAddTalk(talk)){
            session.addTalk(talk);
            return true;
        }
        return false;
    }

        public static Track newTrackAndPutToMap(int trackNumber){
            Track track = Track.getTrack(trackNumber);
            tracks.put(String.valueOf(trackNumber),track);
            return track;
        }

    public static Map<String, Track> getTracks() {
        return tracks;
    }



}
